/*
 * @Descripttion: 
 * @version: 
 * @Author: Zuo
 * @Date: 2021-08-11 17:38:51
 * @LastEditors: Zuo
 * @LastEditTime: 2021-08-12 10:28:17
 */
(function(window){
    function Promise(excutor){
        let self = this;
        self.status = 'pending',
        self.callbacks = [],
        self.value = undefined
        function resolve(value){
            if(self.status !== 'pending'){
                return;
            }
            self.value = value;
            self.status = 'resolved'
            if(self.callbacks.length>0){
                setTimeout(()=>{
                    self.callbacks.forEach(obj => {
                        obj.onResolved(value)
                    });
                },0)
            }
        }

        function reject(value){
            if(self.status !== 'pending'){
                return;
            }
            self.status = 'rejected'
            self.value = value;
            if(self.callbacks.length>0){
                setTimeout(()=>{
                    self.callbacks.forEach(obj => {
                        obj.onRejected(value)
                    });
                },0)
            }
        }
        try{
            excutor(resolve,reject)
        }catch(err){
            reject(err)
        }
    }
    Promise.prototype.then = function(onResolved,onRejected){
        onResolved = typeof onResolved === 'function' ? onResolved : (value) => value;
        onRejected = typeof onRejected === 'function' ? onRejected : (reason) => {throw reason}
        const self = this;
        return new Promise((resolve,reject)=>{
                    function handler(callback){
                        try{
                            const result = callback(self.value);
                            if(result instanceof Promise){
                                result.then(resolve,reject)
                            }else{
                                resolve(result)
                            }
                        }catch(err){
                            reject(err)
                        }
                    }
                    
                    if(self.status === 'pending'){
                        self.callbacks.push({
                            onResolved(){
                                handler(onResolved)
                            },
                            onRejected(){
                                handler(onRejected)
                            }
                        })
                    }else if(self.status === 'resolved'){
                        setTimeout(()=>{
                            handler(onResolved)
                        })
                    }else if(self.status === 'rejected'){
                        setTimeout(()=>{
                            handler(onRejected)
                        })
                    }
                })
    }
    Promise.prototype.catch = function(onRejected){
      return  this.then(undefined,onRejected)
    }

    Promise.resolve = function(value){
        return new Promise((resolve,reject)=>{
            if(value instanceof Promise){
                value.then(resolve,reject)
            }else{
                resolve(value)
            }
       
        })
    }

    Promise.reject = function(value){
        return new Promise((_,reject)=>{
            reject(value)
        })
    }

    Promise.all = function(promises){
        let values = new Array(promises.length);
        let count  = 0;
        return new Promise((reslove,reject)=>{
            promises.forEach((p,index)=>{
                   Promise.resolve(p).then(
                       (value)=>{
                            count++
                            values[index] = value;
                            if(count == promises.length){
                                reslove(values)
                            }
                       },
                       reject
                   )
            })
        })
    }

    Promise.race = function(promises){
        return new Promise((reslove,reject)=>{
            promises.forEach((p)=>{
                   Promise.resolve(p).then(
                      reslove,
                      reject
                   )
            })
        })
    }
    window.Promise = Promise
})(window)